package com.wentao.mall.entity

import com.wentao.mall.dao.OperatorDao
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.web.builders.HttpSecurity
import org.springframework.security.config.annotation.web.builders.WebSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.stereotype.Service
import javax.annotation.PostConstruct
import javax.servlet.http.HttpServletResponse

@EnableWebSecurity
class WebSecurityConfig : WebSecurityConfigurerAdapter() {

    @Autowired
    lateinit var userDetailsService: CustomUserDetailsService

    override fun configure(web: WebSecurity) {
        web.ignoring().antMatchers(
            "/**.js", "/**.css", "/**.svg", "/index.html"
        )

    }

//    @Bean
//    fun corsFilter(): CorsFilter {
//        val configuration = CorsConfiguration()
//        configuration.allowCredentials = true
////        configuration.allowedOrigins = listOf("http://118.25.49.37:8080", "http://118.25.49.37", "http://127.0.0.1:8000", "http://localhost:8000","http://10.254.42.203:10086")
//        configuration.allowedOrigins = listOf("*")
//        configuration.allowedMethods = listOf("*")
////        configuration.allowedMethods = listOf("GET", "HEAD", "POST", "OPTIONS")
//        configuration.exposedHeaders = listOf("Location")
//        val source = UrlBasedCorsConfigurationSource()
//        source.registerCorsConfiguration("/**", configuration)
//        return CorsFilter(source)
//    }

    override fun configure(http: HttpSecurity) {
        http
            .cors().and()
            .csrf().disable()

            .authorizeRequests()
            .antMatchers("/api/login/**")
            .permitAll()

            .anyRequest()
            .authenticated()
//            .permitAll()

            //TODO 区分operator 和 user
            .and().formLogin()
            .loginPage("/api/403")
            .loginProcessingUrl("/api/login/account")
            .failureUrl("/api/login/fail")
            .defaultSuccessUrl("/api/login/success", true)
            .permitAll()

            .and().logout().deleteCookies("JSESSIONID", "jwt")
            .logoutUrl("/api/login/outLogin")
            .logoutSuccessUrl("/api/logout/success")
            .permitAll()

            //  没权限时会进入这个，如果未配置，则进入上面的.loginPage()
            .and().exceptionHandling().authenticationEntryPoint { _, httpServletResponse, authenticationException ->
                // 未授权
                httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.message)
                httpServletResponse
            }
        //org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate

    }

    override fun configure(auth: AuthenticationManagerBuilder) {

        auth.userDetailsService(userDetailsService).passwordEncoder(BCryptPasswordEncoder())
    }

}

@Service
class CustomUserDetailsService(
    val operatorDao: OperatorDao
) : UserDetailsService {

    @PostConstruct
    fun initUser() {
        val username = operatorDao.findByUsername("user")
        username?.let {
            operatorDao.deleteAll()
        }

        val p = BCryptPasswordEncoder().encode("123")

        val operator = Operator("user", p, -1, 2, 3)
        operatorDao.save(operator)

    }

    override fun loadUserByUsername(username: String): UserDetails {
        val operator = operatorDao.findByUsername(username)
        return operator ?: throw UsernameNotFoundException("用户不存在")
    }
}